# -*- coding:utf-8 -*-

import hashlib, os

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, Security, Request

from core.response import success_page, ResponsePage, ResponseModel, success
from core.dependencies import page_filter

from app.models.request.topic import Attachment, AttachmentCreate, AttachmentUpdate
from app.repository.topic import AttachmentRepository

from app.service.user import check_login_user

router = APIRouter(prefix="/attachment")

@router.get("/", response_model=ResponsePage[Attachment], summary="附件列表查询", dependencies=[Security(check_login_user, scopes=["attachment_access"])])
async def attachment_pages(pageNo: int=1, pageSize: int=10
        , page_filter = Depends(page_filter)
        , repo: AttachmentRepository = Depends(AttachmentRepository)):
    data, total_page, total_rows = await repo.get_by_page(pageNo, pageSize, page_filter)
    return success_page(page_no=pageNo, page_size=pageSize, total_page = total_page, total_rows=total_rows, data=data)


@router.get("/{id}", response_model=ResponseModel[Attachment], summary="附件信息查询", dependencies=[Security(check_login_user, scopes=["attachment_access"])])
async def attachment_by_id(id: int, repo: AttachmentRepository = Depends(AttachmentRepository)):
    db_data = await repo.get_model_by_id(id)
    if db_data is None:
        raise HTTPException(status_code=404, detail="Attachment not found")
    return success(data=Attachment.from_orm(db_data))


@router.post("/", response_model=ResponseModel[Attachment], summary="附件创建", dependencies=[Security(check_login_user, scopes=["attachment_create"])])
async def do_create_attachment(data: AttachmentCreate, request: Request, repo: AttachmentRepository = Depends(AttachmentRepository)):
    check_data = (await repo.get_filter(filter={"name": data.name})).first()
    if check_data is not None:
        raise HTTPException(status_code=400, detail="Attachment name already exists")
    check_data = (await repo.get_filter(filter={"hash": data.hash, "status": 2})).first()
    another = {}
    msg="创建文件成功"
    if check_data is not None:
        # 状态设为已上传
        another={"status": 2}
        msg="秒传成功"
    
    data = await repo.save(data, another=another, create_user=request.state.user_id)
    return success(data=data, message=msg)

@router.delete("/{id}", response_model=ResponseModel[Attachment], summary="附件删除", dependencies=[Security(check_login_user, scopes=["attachment_delete"])])
async def do_delete_attachment(id: int, request: Request, repo: AttachmentRepository = Depends(AttachmentRepository)):
    check_data = await repo.get_by_id(id)
    if check_data is None:
        raise HTTPException(status_code=400, detail="Attachment not found")
    data = await repo.delete(id, delete_user=request.state.user_id)
    return success(data=data)


@router.post("/upload", response_model=ResponseModel[Attachment], summary="附件上传", dependencies=[Security(check_login_user, scopes=["attachment_upload"])])
async def do_upload_attachment(request: Request, file: UploadFile = File(), id: int = Form(), repo: AttachmentRepository = Depends(AttachmentRepository)):
    check_data = await repo.get_by_id(id)
    if check_data is None:
        raise HTTPException(status_code=400, detail="Attachment not found")
    if check_data.status == 2:
        raise HTTPException(status_code=400, detail="Attachment already uploaded")
    if check_data.hash is None or check_data.hash.upper() != calculate_md5(file).upper():
        raise HTTPException(status_code=422, detail="File hash not match")
    url = f"{check_data.category}/{check_data.hash}.{check_data.name.rsplit('.', 1)[-1]}"
    await save_file(file, f"data/{url}")
    data = await repo.update(id, Attachment.from_orm({'status': 2, 'size': file.size, 'content_type': file.content_type, 'url': url}), update_user=request.state.user_id)
    return success(data=Attachment.from_orm(data), message="Upload success")


async def save_file(file: UploadFile, path: str):
    file_dir = os.path.dirname(path)
    if not os.path.exists(file_dir):
        os.makedirs(file_dir)
    size = file.size
    save = 0
    with open(path, "wb") as buffer:
        await file.seek(0)
        while chunk := file.file.read(8192):  # 逐块读取文件
            buffer.write(chunk)
            save += len(chunk)
            print(f"已上传 {save}/{size} 字节: {save / size * 100:.2f}%")

    print(f"文件上传完成，保存路径为：{path}")

def calculate_md5(file: UploadFile) -> str:
    # 初始化 MD5 哈希对象
    md5_hash = hashlib.md5()
    
    # 读取文件内容并更新 MD5 哈希值
    while chunk := file.file.read(8192):  # 逐块读取文件
        print(f"已读取 {len(chunk)} 字节")
        md5_hash.update(chunk)
    # 返回文件的 MD5 值
    return md5_hash.hexdigest()